import { reactive } from 'vue'
import type { NavItem, NavEntry } from '@/widgets/types'
import { eventBus, useEventBus } from '@/widgets'

export interface MenuItem {
  path: string
  onClick: () => void
}

const navItems = reactive<NavItem[]>([])

type NavItemX = NavItem & { group?: string }

function resolveNavName(str: string): { group?: string; icon?: string; name: string } {
  const idx = str.indexOf(':')
  let group = undefined
  let name = str
  if (idx > 0) {
    group = str.substring(0, idx)
    name = str.substring(idx + 1)
  }
  let icon: string | undefined = undefined
  if (name.startsWith('{')) {
    const idx1 = name.indexOf('}')
    if (idx1 > 0) {
      icon = name.substring(1, idx1)
      name = name.substring(idx1 + 1)
    }
  }
  return { group, name, icon }
}

function lastIndexOfGroup(lst: NavEntry[], group: string | undefined): number {
  for (let i = lst.length - 1; i >= 0; i--) {
    const e = lst[i]
    if (e === '-') {
      continue
    }
    if ((e as NavItemX).group == group) {
      return i
    }
  }
  return -1
}

function findItem(lst: NavEntry[], group: string | undefined, name: string): NavItemX | null {
  for (let i = 0; i < lst.length; i++) {
    const e = lst[i]
    if (e === '-') {
      continue
    }
    const e1 = e as NavItemX
    if (e1.group == group && e1.name === name) {
      return e
    }
  }
  return null
}

function pushNavItem(lst: NavEntry[], navItem: NavItemX) {
  if (lst.length == 0) {
    lst.push(navItem)
    return
  }
  const gIdx = lastIndexOfGroup(lst, navItem.group)
  if (gIdx === -1) {
    if (!navItem.group) {
      lst.splice(0, 0, navItem, '-')
    } else {
      lst.splice(lst.length, 0, '-', navItem)
    }
  } else {
    lst.splice(gIdx + 1, 0, navItem)
  }
}

function doAddMenu(lst: NavEntry[], path: string[], item: MenuItem) {
  const { group, icon, name } = resolveNavName(path[0])
  if (path.length === 1) {
    pushNavItem(lst, { group, name, icon, onClick: item.onClick })
    return
  }
  let navItem = findItem(lst, group, name)
  if (!navItem) {
    navItem = { name, group, icon, children: [] }
    pushNavItem(lst, navItem)
  }
  if (navItem.children == null) {
    navItem.children = []
  }
  doAddMenu(navItem.children, path.splice(1), item)
}

function addMenu(item: MenuItem) {
  let path: string[]
  if (item.path.startsWith('/')) {
    path = item.path.substring(0).split('/')
  } else {
    path = item.path.split('/')
  }
  doAddMenu(navItems, path, item)
}

const registerAppMenuKey = Symbol('register-app-menu')

export function useNavItems(): NavItem[] {
  useEventBus(registerAppMenuKey, addMenu)
  return navItems
}

export function registerAppMenu(item: MenuItem) {
  eventBus.emit(registerAppMenuKey, item)
}
